﻿using System;
using System.Threading;
using OmegaBot;

namespace drone_cc
{
    public static class DroneCombatClassUtilties
    {
        #region utility functions

        public static SpellKeyDefinition mount1;
        public static SpellKeyDefinition mount2;
        public static int MountID = 0;
        public static GameItem combineitem;

        // Usage: DroneCombatClassUtilties.canCast(somespell) or somespell.canCast()
        // Compliments of Fartbutt
        public static bool canCast(this SpellKeyDefinition theSpell)
        {
            if (theSpell.IsCastable && theSpell.IsDefined)
            {
                return true;
            }
            return false;
        }

        // Usage: DroneCombatClassUtilties.TestAPIExports()
        public static void TestAPIExports()
        {
            GameObject[] all = GameObject.GetAllObjects();

            // also show main hand item!
            Log.WriteLine("main hand equipped item is: {0}", GameItem.GetEquippedItem("MainHandSlot").Name);

            foreach (GameObject one in all)
            {
                switch (one.GameObjectType)
                {
                    case BaseObjectType.Player:
                        Log.WriteLine("- {0:x} / {1}, name: {2}, health: {3}, race: {4}, class: {5}, loc: {6}", one.GUID, one.GameObjectType,
                            ((GamePlayer)one).Name,
                            ((GamePlayer)one).Health,
                            ((GamePlayer)one).PlayerRace.ToString(),
                            ((GamePlayer)one).PlayerClass.ToString(),
                            ((GamePlayer)one).Location.ToString());
                        break;

                    case BaseObjectType.Mob:
                        Log.WriteLine("- {0:x} / {1}, name: {2}, health: {3}, reaction: {4}, loc: {5}", one.GUID, one.GameObjectType,
                            ((GameUnit)one).Name,
                            ((GameUnit)one).Health,
                            ((GameUnit)one).Reaction.ToString(),
                            ((GameUnit)one).Location.ToString());
                        break;

                    case BaseObjectType.Node:
                        Log.WriteLine("- {0:x} / {1}, name: {2}, dispinfo: {3}, loc: {4}", one.GUID, one.GameObjectType,
                            ((GameNode)one).Name,
                            ((GameNode)one).DisplayInfo,
                            ((GameNode)one).Location.ToString());
                        break;

                    case BaseObjectType.Item:
                        Log.WriteLine("- {0:x} / {1}, item #: {2}, durability: {3}/{4}, name: \"{5}\", stacksize: {6}/{7}",
                            one.GUID, one.GameObjectType,
                            ((GameItem)one).ItemNumber,
                            ((GameItem)one).Durability,
                            ((GameItem)one).DurabilityMax,
                            ((GameItem)one).Name,
                            ((GameItem)one).StackSize,
                            ((GameItem)one).StackSizeMax);

                        if (((GameItem)one).HasTempEnchant)
                        {
                            Log.WriteLine("--- item above has a temporary enchant of some kind!  (poison, windfury, lure, etc etc)");
                        }
                        break;

                    case BaseObjectType.Container:
                        Log.WriteLine("- {0:x} / {1}, slots: {2}, name: {3}", one.GUID, one.GameObjectType, ((GameBag)one).Slots, ((GameBag)one).Name);

                        // go through array of Contents to find items that are in this bag!
                        break;

                    default:
                        Log.WriteLine("- {0:x} / {1}", one.GUID, one.GameObjectType);
                        break;
                }
            }
        }

        //Usage DroneCombatClassUtilties.setupMountSpellKeys(SpellKeys);
        public static void setupMountSpellKeys(this SpellKeyBucket SpellKeys)
        {
            DroneCombatClassUtilties.mount1 = SpellKeys.CreateFromSpell("mount1", "18989 6777 35713 49379 23249 65641 23248 35712 35714 65637 23247 18991 17453 17465 18992 63641 580 61425 61447 65642 10796 17454 64659 10799 64657 15779 54753 6898 39319 65645 16083 34897 16081 17229 59791 59793 24242 65639 42777 23338 23251 65643 35028 46628 23223 23240 23228 23222 49322 24252 39318 34899 43688 16056 66906 67466 60114 60116 51412 58983 22719 35022 16055 17461 64977 470 60118 60119 48027 22718 59785 59788 22720 22721 22717 22723 22724 64658 35020 10969 17463 64656 50869 43899 34406 458 18990 6899 54811");
            DroneCombatClassUtilties.mount2 = SpellKeys.CreateFromSpell("mount2", "48025 59797 59799 17459 72286 69696 17450 65917 55531 60424 16084 66846 63640 16082 472 35711 35018 23246 66090 41252 34795 10873 17462 22722 16080 30174 17481 39317 34898 63642 42776 10789 23510 63232 66847 8394 10793 66088 66091 68057 23241 43900 23238 23229 23250 65646 23221 23239 65640 23252 35025 23225 68056 23219 65638 23242 23243 23227 33660 32292 35027 35644 17464 6654 6648 39315 34896 68188 68187 39316 34790 63635 63637 6653 8395 63639 63643 17460 23509 63638 61465 61467 61469 61470 35710 23214 13819 34767 34769");

        }

        //Usage Me.isMounted()
        public static bool isMounted(this MyPlayer Me)
        {
            Buff[] allbuffs = Me.GetUnitBuffs();
            if (DroneCombatClassUtilties.MountID == 0)
            {

                return false;
            }
            foreach (Buff b in allbuffs)
            {
                if (b.SpellID == DroneCombatClassUtilties.MountID || b.SpellID == 31726)
                {
                    return true;
                }
            }
            return false;
        }

        //usage Me.mustMount(Ini)
        public static bool mustMount(this MyPlayer Me, IniManager Ini, string Class)
        {
            GameObject[] allunits = GameObject.GetAllObjects();
            //Min Distance to closest hostile mob or lootable corpse so you can mount
            double MDistance = Convert.ToDouble(Ini.GetString(Class, "mountdistance"));
            foreach (GameObject o in allunits)
            {
                if (o.GameObjectType == BaseObjectType.Mob)
                {
                    if (!Ini.GetBoolean(Class, "skiplootcheck", false))
                    {
                        if (((GameUnit)o).ToString().Contains("Lootable=True") && ((GameUnit)o).Distance < MDistance)
                        {
                            Log.WriteLine("{0} is lootable and too close, not mounting", ((GameUnit)o).Name);
                            return false;
                        }
                    }
                    if ((Convert.ToDouble(((GameUnit)o).Distance)) < MDistance && !((GameUnit)o).IsDead && ((GameUnit)o).Reaction == Reaction.Hostile)
                    {
                        Log.WriteLine("{0} is too close, not mounting", ((GameUnit)o).Name);
                        return false;
                    }
                }
            }

            // There are no units nearby
            return true;
        }

        //usage Me.mountUp(this.Input)
        public static void mountUp(this MyPlayer Me, Input Keyboard)
        {
            Buff[] oldbuffs = Me.GetUnitBuffs();
            if (mount1.IsDefined && mount1.IsCastable)
            {
                Keyboard.ReleaseAllKeys();
                mount1.Cast(CastOptions.ExpectCastBar);
                Buff[] newbuffs = Me.GetUnitBuffs();
                Buff oldbuff = null;
                foreach (Buff b in newbuffs)
                {
                    oldbuff = null;
                    foreach (Buff old in oldbuffs)
                    {
                        if (b.SpellID == old.SpellID || b.SpellID == 31726)
                        {
                            oldbuff = b;
                        }
                    }
                    if (oldbuff == null)
                    {
                        MountID = b.SpellID;
                        Log.WriteLine("Mount Name {0}, Spell ID {1}", b.SpellName, b.SpellID);
                    }

                }
            }
            if (mount2.IsDefined && mount2.IsCastable)
            {
                Keyboard.ReleaseAllKeys();
                mount2.Cast(CastOptions.ExpectCastBar);
                Buff[] newbuffs = Me.GetUnitBuffs();
                Buff oldbuff = null;
                foreach (Buff b in newbuffs)
                {
                    oldbuff = null;
                    foreach (Buff old in oldbuffs)
                    {
                        if (b.SpellID == old.SpellID || b.SpellID == 31726)
                        {
                            oldbuff = b;
                        }
                    }
                    if (oldbuff == null)
                    {
                        MountID = b.SpellID;
                        Log.WriteLine("Mount Name {0}, Spell ID {1}", b.SpellName, b.SpellID);
                    }

                }
            }
        }


        public static void dismount(this MyPlayer Me)
        {

            if (mount1.IsDefined)
            {
                mount1.Cast(CastOptions.FastReturn);
            }
            if (mount2.IsDefined)
            {
                mount2.Cast(CastOptions.FastReturn);
            }

        }

        public static bool needCombine()
        {
            GameObject[] allObjects = GameObject.GetAllObjects();
            foreach (GameObject v in allObjects)
            {
                if (v.GameObjectType == BaseObjectType.Item)
                {
                    if ((((GameItem)v).ItemNumber == 37705 || //water
                        ((GameItem)v).ItemNumber == 37701 || //earth
                        ((GameItem)v).ItemNumber == 37704 || //life
                        ((GameItem)v).ItemNumber == 37700 || //air
                        ((GameItem)v).ItemNumber == 37703 || //shadow
                        ((GameItem)v).ItemNumber == 37702 || //fire
                        ((GameItem)v).ItemNumber == 22578 || //water mote
                        ((GameItem)v).ItemNumber == 22573 || //earth mote
                        ((GameItem)v).ItemNumber == 22575 || //life mote
                        ((GameItem)v).ItemNumber == 22572 || //air mote
                        ((GameItem)v).ItemNumber == 22577 || //shadow mote
                        ((GameItem)v).ItemNumber == 22576 || //mana mote
                        ((GameItem)v).ItemNumber == 22574) && //fire mote

                        ((GameItem)v).StackSize >= 10)
                    {
                        combineitem = ((GameItem)v);
                        return true;
                    }
                }
            }
            return false;
        }

        public static bool needOpenClams()
        {
            GameObject[] allObjects = GameObject.GetAllObjects();
            foreach (GameObject v in allObjects)
            {
                if (v.GameObjectType == BaseObjectType.Item)
                {
                    if (
                        ((GameItem)v).ItemNumber == 7973 || //Big-Mouth Clam
                        ((GameItem)v).ItemNumber == 44700 || //Brooding Darkwater Clam
                        ((GameItem)v).ItemNumber == 36781 || //Darkwater Clam
                        ((GameItem)v).ItemNumber == 24476 || //Jaggal Clam
                        ((GameItem)v).ItemNumber == 5523 || //Small Barnacled Clam
                        ((GameItem)v).ItemNumber == 15874 || //Soft-shelled Clam
                        ((GameItem)v).ItemNumber == 5524 || //Thick-shelled Clam
                        ((GameItem)v).ItemNumber == 45909 //Giant Darkwater Clam
                        )
                    {
                        combineitem = ((GameItem)v);
                        return true;
                    }
                }
            }
            return false;
        }

        public static void combineItems(this Input Keyboard)
        {
            Keyboard.ReleaseAllKeys();
            Keyboard.SendTextNow("/use " + combineitem.Name);
            Keyboard.PressKey(13);

        }
        #endregion
    }

}
